/****************************************************************************
 * Chariott - Continuous Integration Testing Tool
 * Zaid Mohsin
 * The University of York
 * 2012/2013
 * MSc in Information Technology
 * All rights reserved.
 ****************************************************************************/
package chariott.partition;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

import org.apache.commons.collections.MultiHashMap;
import org.apache.commons.collections.MultiMap;
import org.jdom2.Element;

import chariott.testing.RunItem;

/**
 * an implementation of AlgorithmOrder that orders the run items by Bin Packing
 * First Fit Decreasing algorithm.
 * 
 * @author Zaid
 * 
 */
public class BinPackingOrder_FF_DEC extends AlgorithmOrder {

	private double binSize;
	private double[] binSizes;
	private MultiMap sortingMap;

	public BinPackingOrder_FF_DEC(int numOfNodes,
			ArrayList<RunItem> itemsToRun, double binSize) {
		super(numOfNodes, itemsToRun);
		this.binSize = binSize;

		sortingMap = new MultiHashMap();
		binSizes = new double[numOfNodes];

		Arrays.fill(binSizes, binSize);

		// sort the items to run by decreasing order
		Collections.sort(itemsToRun, new Comparator<RunItem>() {
			public int compare(RunItem i1, RunItem i2) {

				return (int) Math.signum(i2.getWeight() - i1.getWeight());
			}
		});

	}

	public MultiMap generateRuns() {

		for (int i = 0; i < itemsToRun.size(); i++) {
			for (int j = 0; j < numOfNodes; j++) {
				if (checkAvailability(j, itemsToRun.get(i))) {
					assignItem(j, itemsToRun.get(i));
					break;
				}
			}
		}

		// System.out.println(sortingMap);
		return sortingMap;

	}

	private void assignItem(int i, RunItem myItem) {

		binSizes[i] = binSizes[i] - myItem.getWeight();
		sortingMap.put(i, myItem);
	}

	private boolean checkAvailability(int i, RunItem myItem) {
		return ((binSizes[i] - myItem.getWeight()) < 0) ? false : true;

	}
}
